package com.jieshuibao.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.jieshuibao.common.config.Global;
import com.jieshuibao.model.db.User;
import com.jieshuibao.model.domain.CookieUser;
import com.jieshuibao.model.domain.WxOrderReq;
import com.jieshuibao.service.RedisService;
import com.jieshuibao.service.UserService;
import com.jieshuibao.service.WeiXinPayService;
import com.jieshuibao.service.WxOrderService;
import com.jieshuibao.util.AesUtil;
import com.jieshuibao.util.UUIDGenerator;
import com.jieshuibao.wx.po.WxAppPayReq;
import com.jieshuibao.wx.po.WxAppPayRes;
import com.jieshuibao.wx.po.WxEnterpriseReq;
import com.jieshuibao.wx.po.WxEnterpriseRes;
import com.jieshuibao.wx.po.WxH5PayReq;
import com.jieshuibao.wx.po.WxJsPayReq;
import com.jieshuibao.wx.po.WxQueryOrderReq;
import com.jieshuibao.wx.po.WxQueryOrderRes;
import com.jieshuibao.wx.util.PayCommonUtil;
import com.jieshuibao.wx.util.WeiXinPublicUtil;
import com.jieshuibao.wx.util.XMLUtil;


//http://blog.csdn.net/gbguanbo/article/details/50915333
//http://www.cnblogs.com/yimiyan/p/5603657.html
//不错 http://www.cnblogs.com/xu-xiang/p/5797575.html
@Controller
@RequestMapping("/api")
public class WeiXinPayController {
    protected static Logger logger = Logger.getLogger(WeiXinPayController.class);
    
    @Value("${server.url}")
    private String host;
    
    @Resource
	private RedisService redisService;
    
    @Resource
    private WxOrderService wxOrderService;
    
    @Resource
    private WeiXinPayService weiXinPayService;
    
    @Resource
    private UserService userService;
    
    String timeMillis = String.valueOf(System.currentTimeMillis() / 1000);
    String randomString = PayCommonUtil.getRandomString(32);
    
    /**
     * @param sn            订单号
     * @param totalAmount    支付金额
     * @param description    产品描述
     * @param request
     * @return
     */
    @RequestMapping(value = "/weixin/hPay",
            method = RequestMethod.POST)
    @ResponseBody    
    public SortedMap<String, Object> ToPay(
    		HttpServletRequest request, @RequestBody WxH5PayReq wxH5PayReq) {
    	String openId = wxH5PayReq.getOpenid();
    	Double unitPrice = wxH5PayReq.getUnitPrice();
    	int amount = wxH5PayReq.getAmount()  == 0 ? 1 : wxH5PayReq.getAmount();;
    	BigDecimal totalAmount = new BigDecimal(unitPrice*amount);
    	String sn = UUIDGenerator.getUUID();// 商户订单号
    	String description = wxH5PayReq.getProductName();
    	
        Map<String, String> map = weixinPrePay(sn,totalAmount,description,openId,request);  
        SortedMap<String, Object> finalpackage = new TreeMap<String, Object>();
        finalpackage.put("appId", WeiXinPublicUtil.PUBLICAPPID);  
        finalpackage.put("timeStamp", timeMillis);  
        finalpackage.put("nonceStr", randomString);  
        finalpackage.put("package", "prepay_id="+map.get("prepay_id"));
        finalpackage.put("signType", "MD5");
        String sign = PayCommonUtil.createSign("UTF-8", finalpackage);  
        finalpackage.put("paySign", sign);
        return finalpackage;
    } 
    
    @SuppressWarnings("unchecked")
    public Map<String, String> weixinPrePay(String sn,BigDecimal totalAmount,  
            String description, String openid,HttpServletRequest request) { 
        SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();  
        parameterMap.put("appid", WeiXinPublicUtil.PUBLICAPPID);  
        parameterMap.put("mch_id", PayCommonUtil.MCH_ID);  
        parameterMap.put("nonce_str", randomString);  
        parameterMap.put("body", description);
        parameterMap.put("out_trade_no", sn);
        parameterMap.put("fee_type", "CNY");  
        BigDecimal total = totalAmount.multiply(new BigDecimal(100));  
        java.text.DecimalFormat df=new java.text.DecimalFormat("0");  
        parameterMap.put("total_fee", df.format(total));  
        System.out.println("jiner2");  
        parameterMap.put("spbill_create_ip", request.getRemoteAddr());  
        parameterMap.put("notify_url", host + "/api/weixin/payCallback");  
        parameterMap.put("trade_type", "JSAPI");
        //trade_type为JSAPI是 openid为必填项
        parameterMap.put("openid", openid);
        System.out.println("");  
        String sign = PayCommonUtil.createSign("UTF-8", parameterMap); 
        System.out.println("jiner2");  
        parameterMap.put("sign", sign);  
        String requestXML = PayCommonUtil.getRequestXml(parameterMap);  
        System.out.println(requestXML);  
        String result = PayCommonUtil.httpsRequest(  
                "https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",  
                requestXML);  
        System.out.println(result);  
        Map<String, String> map = null;  
        try {  
            map = PayCommonUtil.doXMLParse(result);  
        } catch (JDOMException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return map;        
    }
    /**
     * 微信APP支付统一下单
     * @param wxAppPayReq
     * @param request
     * @return
     * @throws JsonProcessingException
     */
    @RequestMapping(value = "/weixin/appPay",method = RequestMethod.POST)
    @ResponseBody
    public Object appPay(@RequestBody WxAppPayReq wxAppPayReq,
    		HttpServletRequest request) throws JsonProcessingException{
    	WxAppPayRes wxAppPayRes = (WxAppPayRes) weiXinPayService.appPay(wxAppPayReq, request);
    	
		return wxAppPayRes;
    }
    /**
     * 微信jssdk支付统一下单
     * @param req
     * @param request
     * @return
     */
    @RequestMapping(value = "/weixin/jsSdkPay",method = RequestMethod.POST)
    @ResponseBody
    public Object jsSdkPay(@RequestBody WxJsPayReq req,HttpServletRequest request){
    	return	weiXinPayService.jSSDKPayInfo(req, request);
    }
    
    @SuppressWarnings("static-access")
	@RequestMapping(value="/weixin/payCallback",method=RequestMethod.POST)
    public void wxCallback(HttpServletRequest request,HttpServletResponse response) throws IOException{
    	request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json;charset=UTF-8");
		try {
			synchronized (this) {
			Map<String, String> kvm = XMLUtil.parseRequestXmlToMap(request);
			if (weiXinPayService.checkAPPCallbackDataSignature(kvm,
					kvm.get("sign"))) {
				logger.warn("微信回调结果json:" + PayCommonUtil.toJson(kvm));
				String return_code = kvm.get("return_code"); // 通信状态
				String result_code = kvm.get("result_code"); // 交易状态
				if (return_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
					if (result_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
						try {
							weiXinPayService.afterPaySuc(kvm);
							logger.warn("out_trade_no: " + kvm.get("out_trade_no") + " pay SUCCESS!");
	                        response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
						} catch (Exception e) {
							logger.error("微信支付回调失败:" + e);
							e.printStackTrace();
						}
					} else {
						// 交易失败
						 WeiXinPayController.logger.error("out_trade_no: "
		                            + kvm.get("out_trade_no") + " result_code is FAIL");
		                        response.getWriter().write(
		                            "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[result_code is FAIL]]></return_msg></xml>");
						logger.error("微信回调交易异常 result_code:" + result_code);
					}
				} else {
					// 通信异常
					logger.error("微信回调通信异常 return_code:" + return_code);
				}
			} else {
				response.getWriter()
						.write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[check signature FAIL]]></return_msg></xml>");
				this.logger.error("out_trade_no: " + kvm.get("out_trade_no")
						+ " check signature FAIL");
			}
		}
		}catch (Exception e1) {
			e1.printStackTrace();
			logger.error("微信回调异常");
		}
    }
    /**
     * APP端查询微信支付
     * @param wxQueryOrderReq
     * @return
     */
    @SuppressWarnings("unchecked")
	@RequestMapping(value="/weixin/queryOrder",method = RequestMethod.POST)
    @ResponseBody
    public Object queryOrder(@RequestBody WxQueryOrderReq wxQueryOrderReq){
    	WxQueryOrderRes wxQueryOrderRes = new WxQueryOrderRes();
    	try {
			String mchOrderNo = wxQueryOrderReq.getOrderMchNo();//商户订单号 
			if(StringUtils.isEmpty(mchOrderNo)){
				wxQueryOrderRes.setCode(PayCommonUtil.FAIL_CODE);
				wxQueryOrderRes.setDes("缺少订单号参数");
				return wxQueryOrderRes;
			}
			SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();  
			parameterMap.put("appid", PayCommonUtil.APPID);  
			parameterMap.put("mch_id", PayCommonUtil.MCH_ID);  
			parameterMap.put("out_trade_no", mchOrderNo);
			parameterMap.put("nonce_str", randomString);  
			String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
			parameterMap.put("sign", sign);  
			String requestXML = PayCommonUtil.getRequestXml(parameterMap);  
			logger.info("微信查询订单请求报文："+requestXML);  
			String result = PayCommonUtil.httpsRequest(PayCommonUtil.API_QUERYSERVER, "POST",  requestXML);  
			logger.info("微信查询订单返回报文"+result);  
			Map<String, String> map = null;  
			map = PayCommonUtil.doXMLParse(result);  
			String return_code  = map.get("return_code");
			String result_code  = map.get("result_code");
			String err_code = map.get("err_code");
			String trade_state = map.get("trade_state");
			String trade_state_desc  = map.get("trade_state_desc");
			String err_code_des = map.get("err_code_des");
			logger.info("微信查询订单json"+PayCommonUtil.toJson(map));
			if (return_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
				if (result_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
					if(trade_state.equalsIgnoreCase(PayCommonUtil.SUCCESS)){
						wxQueryOrderRes.setCode(PayCommonUtil.SUCCESS_CODE);
						wxQueryOrderRes.setDes("支付成功");
					}else if(trade_state.equalsIgnoreCase("REFUND")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.REFUND);
						wxQueryOrderRes.setDes("转入退款");
					}else if(trade_state.equalsIgnoreCase("NOTPAY")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.NOTPAY);
						wxQueryOrderRes.setDes("未支付");
					}else if(trade_state.equalsIgnoreCase("CLOSED")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.CLOSED);
						wxQueryOrderRes.setDes("已关闭");
					}else if(trade_state.equalsIgnoreCase("REVOKED")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.REVOKED);
						wxQueryOrderRes.setDes("已撤销（刷卡支付）");
					}else if(trade_state.equalsIgnoreCase("USERPAYING")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.USERPAYING);
						wxQueryOrderRes.setDes("用户支付中");
					}else if(trade_state.equalsIgnoreCase("PAYERROR")){
						wxQueryOrderRes.setCode(WxQueryOrderRes.PAYERROR);
						wxQueryOrderRes.setDes("支付失败(其他原因，如银行返回失败)");
					}
					logger.info("mchOrderNo:"+mchOrderNo+",trade_state:"+trade_state+",trade_state_desc:"+trade_state_desc);
				}else{
					if(err_code.equalsIgnoreCase("ORDERNOTEXIST")){
						logger.info("此交易订单号--"+mchOrderNo+"--不存在");
					}else if(err_code.equalsIgnoreCase("SYSTEMERROR")){
						logger.info("微信查询订单系统错误");
					}
					logger.info("mchOrderNo:"+mchOrderNo+",result_code:"+result_code+",err_code:"+err_code+",err_code_des:"+err_code_des);
					wxQueryOrderRes.setCode(PayCommonUtil.FAIL_CODE);
					wxQueryOrderRes.setDes(err_code_des);
				}
			}else{
				logger.info("微信查询订单通信异常");
				wxQueryOrderRes.setCode(PayCommonUtil.FAIL_CODE);
				wxQueryOrderRes.setDes("支付失败");
			}
		} catch (JDOMException e) {
			logger.error("JDOMException:xml解析异常");
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("IOException:解析异常");
			e.printStackTrace();
		}
    	return wxQueryOrderRes;
    }
    
    @RequestMapping(value="/weixin/{version}/queryOrder",method = RequestMethod.POST)
    @ResponseBody
    public Object queryOrder(@PathVariable String version ,@RequestBody WxQueryOrderReq wxQueryOrderReq){
    	WxQueryOrderRes res = new WxQueryOrderRes();
    	try {
    		if(StringUtils.isNotEmpty(version)){
    			
    		}
			String partner_trade_no = wxQueryOrderReq.getOrderMchNo();//商户订单号 
			String src = wxQueryOrderReq.getSrc();
			if(StringUtils.isEmpty(partner_trade_no)){
				res.setCode(PayCommonUtil.FAIL_CODE);
				res.setDes("缺少订单号参数");
				return res;
			}
			res = weiXinPayService.queryOrder(version,src,partner_trade_no);
    	}catch(Exception e){
    		res.setCode(PayCommonUtil.FAIL_CODE);
			res.setDes("系统繁忙");
    	}
    	return res;
    }
    /**
     * 提现  企业付款到个人
     * @param wxEnterpriseReq
     * @param request
     * @return
     */
	@RequestMapping(value="weixin/payToIndividual",method=RequestMethod.POST)
    @ResponseBody
    public Object payToIndividual(@RequestBody WxEnterpriseReq wxEnterpriseReq,HttpServletRequest request){
    	WxEnterpriseRes res = new WxEnterpriseRes();
    	
    	String cookieId = request.getHeader("cookieId");
    	if(StringUtils.isEmpty(cookieId)){
    		res.setCode(Global.NOTLOGIN);
    		res.setDes("未登录");
    		return res;
    	}else{
    		res.setCode(Global.FAIL);
    		res.setDes("请下载最新版本，如有疑问请联系客服0101-57797070转817");
    		return res;
    	}
//    	CookieUser cookieUser = redisService.getObejct(cookieId,CookieUser.class);
//    	if(null == cookieUser){
//    		res.setCode(Global.NOTLOGIN);
//    		res.setDes("未登录");
//    		return res;
//    	}
//    	String phoneNumber = cookieUser.getPhoneNumber();
//    	User userByPhone = userService.getUserByPhoneNumber(phoneNumber);
//    	res = weiXinPayService.updatePayEnterprise(userByPhone,wxEnterpriseReq,request);
//    	return res;
    }
	
	 /**
     * 提现  企业付款到个人V1.0
     * @param wxEnterpriseReq
     * @param request
     * @return
     */
	@RequestMapping(value="{version}/wx/payToIndividual",method=RequestMethod.POST)
    @ResponseBody
    public Object payToPersonal(@RequestBody WxEnterpriseReq wxEnterpriseReq,@PathVariable String version,HttpServletRequest request){
    	WxEnterpriseRes res = new WxEnterpriseRes();
    	String cookieId = request.getHeader("cookieId");
    	if(StringUtils.isEmpty(cookieId)){
    		res.setCode(Global.NOTLOGIN);
    		res.setDes("未登录");
    		return res;
    	}
    	CookieUser cookieUser = redisService.getObejct(cookieId,CookieUser.class);
    	if(null == cookieUser){
    		res.setCode(Global.NOTLOGIN);
    		res.setDes("未登录");
    		return res;
    	}
    	String phoneNumber = cookieUser.getPhoneNumber();
    	User userByPhone = userService.getUserByPhoneNumber(phoneNumber);
    	if("1.0".equals(version)){
    		if(StringUtils.isEmpty(userByPhone.getUserName())){
    			res.setCode(PayCommonUtil.WARN_CODE);
        		res.setDes("未填写真实姓名");
        		return res;
    		}
    		res = weiXinPayService.updatePayPersonal(userByPhone,wxEnterpriseReq,request);
    		return res;
    	}else{
    		res.setCode(Global.FAIL);
    		res.setDes("系统繁忙");
    		return res;
    	}
    }
    /**
     * 企业支付查询订单
     * @param partner_trade_no
     * @param request
     * @return
     */
    @RequestMapping(value="weixin/enterpriseOrder/{partner_trade_no}",method=RequestMethod.POST)
    @ResponseBody
    public Object enterpriseOrder(@PathVariable  String partner_trade_no,HttpServletRequest request){
    	WxEnterpriseRes res = weiXinPayService.enterpriseOrder(partner_trade_no);
    	return res;
    }
    
    /**
     * 微信退款回调
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/wx/refundBack", method = RequestMethod.POST)
	public void refundWxCallback(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json;charset=UTF-8");
	
		try {
			synchronized (this) {
				Map<String, String> kvm = XMLUtil.parseRequestXmlToMap(request);
				logger.info("微信退款回调结果json:" + PayCommonUtil.toJson(kvm));
				//boolean signatureValid = PayCommonUtil.isSignatureValid(kvm, PayCommonUtil.API_KEY);
				//boolean checkAPPCallbackDataSignature = weiXinPayService.checkAPPCallbackDataSignature(kvm,
						//kvm.get("sign"));
				
				//if (checkAPPCallbackDataSignature) {
					//logger.warn("微信回调结果json:" + PayCommonUtil.toJson(kvm));
					String return_code = kvm.get("return_code"); // 通信状态
					//String result_code = kvm.get("result_code"); // 退款状态
					String return_msg = kvm.get("return_msg");//错误原因
					if (return_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
						String req_info = kvm.get("req_info");
							try {
								
								String decryptData = AesUtil.decryptData(req_info);
								Map<String, String> doXMLParse = PayCommonUtil.xmlToMap(decryptData);
								
								weiXinPayService.refundWeixinBack(doXMLParse);
								logger.info("微信退款回调通信成功 return_code:" + return_code+"="+return_msg);
								response.getWriter()
								.write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
							} catch (Exception e) {
								logger.error("微信解密失败:" + req_info);
								e.printStackTrace();
							}
						
					} else {
						// 回调通信
						logger.info("微信退款回调通信异常 return_code:" + return_code+"="+return_msg);
					}
				/*} else {
					response.getWriter()
							.write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[check signature FAIL]]></return_msg></xml>");
					logger.info("签名验证失败=return_code: " + kvm.get("return_code")+"=return_msg:"+kvm.get("return_msg")
							+ " check signature FAIL");
				}*/
			}
		} catch (Exception e1) {
			e1.printStackTrace();
			logger.info("微信退款回调异常："+request);
		}
	}
	@RequestMapping(value = "/refund/order", method = RequestMethod.POST)
	@ResponseBody
	public Object checkWxRefund(HttpServletRequest request,
			@RequestBody WxOrderReq req) {
		return weiXinPayService.checkRefund(req.getMchOrderNo(),req.getType());
	}
    
}